#pragma once
#include "reactor/noncopyable.hpp"
#include "reactor/buffer.hpp"
#include <functional>
#include <memory>
#include <string>
#include <netinet/in.h>

namespace reactor {
class EventLoop;
class Channel;

/**
 * @brief 封装一个 TCP 连接
 */
class TcpConnection : noncopyable, public std::enable_shared_from_this<TcpConnection> {
public:
    using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
    using ConnectionCallback = std::function<void(const TcpConnectionPtr&)>;
    using MessageCallback = std::function<void(const TcpConnectionPtr&, Buffer*)>;
    using CloseCallback = std::function<void(const TcpConnectionPtr&)>;

    TcpConnection(EventLoop* loop, int sockfd, const struct sockaddr_in& localAddr, const struct sockaddr_in& peerAddr);
    ~TcpConnection();

    void send(const std::string& message);
    void shutdown();
    
    // 当连接建立时由 TcpServer 调用
    void connectEstablished();
    // 当连接销毁时由 TcpServer 调用
    void connectDestroyed();
    
    EventLoop* getLoop() const { return _loop; }
    int sockfd() const { return _sockfd; }
    const struct sockaddr_in& peerAddress() const { return _peerAddr; }
    const struct sockaddr_in& localAddress() const { return _localAddr; }
    bool connected() const { return _state == kConnected; }

    void setConnectionCallback(const ConnectionCallback& cb) { _connectionCallback = cb; }
    void setMessageCallback(const MessageCallback& cb) { _messageCallback = cb; }
    void setCloseCallback(const CloseCallback& cb) { _closeCallback = cb; }

private:
    enum StateE { kConnecting, kConnected, kDisconnecting, kDisconnected, };
    void setState(StateE s) { _state = s; }

    void handleRead();
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const std::string& message);
    void shutdownInLoop();

    EventLoop* _loop;
    int _sockfd;
    StateE _state;
    std::unique_ptr<Channel> _channel;
    
    const struct sockaddr_in _localAddr;
    const struct sockaddr_in _peerAddr;
    
    ConnectionCallback _connectionCallback;
    MessageCallback _messageCallback;
    CloseCallback _closeCallback;

    Buffer _inputBuffer;
    Buffer _outputBuffer;
};
} // namespace reactor
